Preparing the Environment

library(highcharter)
library(forecast)
library(dplyr)
library(quantmod)
library(modeltime)
tickers <- readxl::read_xlsx('data_input/Yahoo Ticker Symbols - September 2017.xlsx', sheet = 'Stock', col_names = FALSE)[-(1:4), c(1,2)]
colnames(tickers) <- c('ticker_', 'name')
ticker <- 'BBCA.JK'
name <- tickers %>% filter(ticker_ == ticker) %>% pull(name) %>% toString()
ticker
## [1] "BBCA.JK"
name
## [1] "PT Bank Central Asia Tbk"
df <- getSymbols(ticker, auto.assign= FALSE)
head(df)
##            BBCA.JK.Open BBCA.JK.High BBCA.JK.Low BBCA.JK.Close BBCA.JK.Volume
## 2007-01-02         2625         2625        2575          2625       15400000
## 2007-01-03         2575         2625        2575          2575       23496000
## 2007-01-04         2600         2600        2550          2600       26830000
## 2007-01-05         2600         2600        2575          2600       14040000
## 2007-01-08         2625         2625        2575          2625       27296000
## 2007-01-09         2600         2625        2550          2600       34384000
##            BBCA.JK.Adjusted
## 2007-01-02         2044.696
## 2007-01-03         2005.749
## 2007-01-04         2025.223
## 2007-01-05         2025.223
## 2007-01-08         2044.696
## 2007-01-09         2025.223
tail(df)
##            BBCA.JK.Open BBCA.JK.High BBCA.JK.Low BBCA.JK.Close BBCA.JK.Volume
## 2020-08-07        31325        31425       30800         30900        8724200
## 2020-08-10        30900        31000       30525         30600        7554900
## 2020-08-11        30700        31000       30650         30875        7759100
## 2020-08-12        30875        31300       30800         31300        7122400
## 2020-08-13        31300        31500       30900         31500        9716200
## 2020-08-14        31500        32025       31200         32025       11463200
##            BBCA.JK.Adjusted
## 2020-08-07            30900
## 2020-08-10            30600
## 2020-08-11            30875
## 2020-08-12            31300
## 2020-08-13            31500
## 2020-08-14            32025
summary(df)
##      Index             BBCA.JK.Open    BBCA.JK.High    BBCA.JK.Low   
##  Min.   :2007-01-02   Min.   : 2100   Min.   : 2225   Min.   : 2000  
##  1st Qu.:2010-06-17   1st Qu.: 5750   1st Qu.: 5850   1st Qu.: 5650  
##  Median :2013-11-21   Median :10550   Median :10700   Median :10450  
##  Mean   :2013-11-13   Mean   :12613   Mean   :12739   Mean   :12481  
##  3rd Qu.:2017-05-02   3rd Qu.:17500   3rd Qu.:17700   3rd Qu.:17300  
##  Max.   :2020-08-14   Max.   :34750   Max.   :35300   Max.   :34175  
##                       NA's   :8       NA's   :8       NA's   :8      
##  BBCA.JK.Close   BBCA.JK.Volume      BBCA.JK.Adjusted
##  Min.   : 2025   Min.   :        0   Min.   : 1715   
##  1st Qu.: 5750   1st Qu.:  8804500   1st Qu.: 4951   
##  Median :10600   Median : 13200700   Median : 9590   
##  Mean   :12614   Mean   : 16542994   Mean   :11845   
##  3rd Qu.:17525   3rd Qu.: 19755100   3rd Qu.:16722   
##  Max.   :34375   Max.   :217114000   Max.   :33791   
##  NA's   :8       NA's   :8           NA's   :8

We have some missing values, lets check where are they.

df %>% subset(is.na(BBCA.JK.Open))
##            BBCA.JK.Open BBCA.JK.High BBCA.JK.Low BBCA.JK.Close BBCA.JK.Volume
## 2008-10-09           NA           NA          NA            NA             NA
## 2008-10-10           NA           NA          NA            NA             NA
## 2008-12-31           NA           NA          NA            NA             NA
## 2009-04-09           NA           NA          NA            NA             NA
## 2009-05-21           NA           NA          NA            NA             NA
## 2009-07-08           NA           NA          NA            NA             NA
## 2009-07-20           NA           NA          NA            NA             NA
## 2011-07-04           NA           NA          NA            NA             NA
##            BBCA.JK.Adjusted
## 2008-10-09               NA
## 2008-10-10               NA
## 2008-12-31               NA
## 2009-04-09               NA
## 2009-05-21               NA
## 2009-07-08               NA
## 2009-07-20               NA
## 2011-07-04               NA

Since this is time series data, I will use time series interpolation to fill the missing values

impute_ts <- function(x){
  x <- ts(x, 1, length(x))
  na.interp(x)
}
# function testing
df[, 1] %>% impute_ts() %>% summary()
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    2100    5700   10550   12592   17500   34750
df[, 2] %>% impute_ts() %>% summary()
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    2225    5800   10700   12718   17650   35300
impute_df <- function(df){
  for (i in 1:length(df[1,])){
    df[, i] <- df[, i] %>% impute_ts()
  }
  df
}

df %>% impute_df() %>% summary()
##      Index             BBCA.JK.Open    BBCA.JK.High    BBCA.JK.Low   
##  Min.   :2007-01-02   Min.   : 2100   Min.   : 2225   Min.   : 2000  
##  1st Qu.:2010-06-17   1st Qu.: 5700   1st Qu.: 5800   1st Qu.: 5600  
##  Median :2013-11-21   Median :10550   Median :10700   Median :10450  
##  Mean   :2013-11-13   Mean   :12592   Mean   :12718   Mean   :12460  
##  3rd Qu.:2017-05-02   3rd Qu.:17500   3rd Qu.:17650   3rd Qu.:17250  
##  Max.   :2020-08-14   Max.   :34750   Max.   :35300   Max.   :34175  
##  BBCA.JK.Close   BBCA.JK.Volume      BBCA.JK.Adjusted
##  Min.   : 2025   Min.   :        0   Min.   : 1715   
##  1st Qu.: 5700   1st Qu.:  8821500   1st Qu.: 4931   
##  Median :10600   Median : 13200700   Median : 9562   
##  Mean   :12593   Mean   : 16548159   Mean   :11825   
##  3rd Qu.:17475   3rd Qu.: 19784000   3rd Qu.:16651   
##  Max.   :34375   Max.   :217114000   Max.   :33791

Applying the imputation function

df <- df %>% impute_df()
tail(RSI(df[ ,4]))
## Warning: timezone of object (UTC) is different than current timezone ().
##                 rsi
## 2020-08-07 56.12723
## 2020-08-10 52.38342
## 2020-08-11 55.32513
## 2020-08-12 59.49037
## 2020-08-13 61.31810
## 2020-08-14 65.69372
tail(BBands(df[, 2:4]))
## Warning: timezone of object (UTC) is different than current timezone ().
##                  dn     mavg       up      pctB
## 2020-08-07 30387.86 30806.25 31224.64 0.7813349
## 2020-08-10 30378.82 30798.33 31217.84 0.3927321
## 2020-08-11 30378.13 30794.17 31210.20 0.5570864
## 2020-08-12 30367.12 30808.33 31249.54 0.8683050
## 2020-08-13 30338.71 30828.33 31317.96 0.9816604
## 2020-08-14 30238.84 30872.50 31506.16 1.1924012
tail(MACD(df[, 4]))
## Warning: timezone of object (UTC) is different than current timezone ().
##                macd   signal
## 2020-08-07 1.516167 1.818648
## 2020-08-10 1.328539 1.720626
## 2020-08-11 1.237662 1.624033
## 2020-08-12 1.262187 1.551664
## 2020-08-13 1.318129 1.504957
## 2020-08-14 1.481010 1.500168
short_ma_ser <- SMA(df[, 4], 20)
long_ma_ser <- SMA(df[, 4], 100)

hcPlotStock <- function(df, ticker_name, ticker, show_ma = TRUE, show_bbands = FALSE, show_volume = TRUE, show_macd = FALSE, show_rsi = TRUE, short_ma = short_ma_ser, long_ma = long_ma_ser){
  # colnames(df) <- c('Open', 'High', 'Low', 'Close', 'Volume', 'Adjusted')
  n_axis <- show_volume + show_macd + show_rsi + 1
  height_axis <- c(2, seq(1, 1, length.out = n_axis - 1))
  y_macd <- 1 + show_volume
  y_rsi <- 1 + show_volume + show_macd
  hcChart <- highchart(type = 'stock') %>% 
    # create axis
    hc_yAxis_multiples(create_yaxis(n_axis, height = height_axis, turnopposite = TRUE)) %>% 
    # decimals setting
    hc_tooltip(valueDecimals = 2)
  
  if(show_volume){
    hcChart <- hcChart %>% 
      ## Add volume
      hc_add_series(df[, 5], color = "orange", yAxis = 1, name = "Volume", type = "column", showInLegend = FALSE)
  }
  
  if(show_macd){
    # calculate MACD
    macd <- MACD(df[, 4], 12, 26, 9) 
    macd$diff <- macd$macd - macd$signal
    diff.high <- ifelse(macd$diff > 0, macd$diff, 0)
    diff.low <- ifelse(macd$diff < 0, macd$diff, 0)
    hcChart <- hcChart %>% 
      # set Bar Chart Stacking Option
      hc_plotOptions(column = list(stacking = "normal")) %>% 
      ## Add MACD
      hc_add_series(diff.high, yAxis = y_macd, name = 'MACD diff', type = 'column', color = 'green', showInLegend = FALSE, enableMouseTracking = FALSE, stack = 'diff') %>% 
      hc_add_series(diff.low, yAxis = y_macd, name = 'MACD diff', type = 'column', color = 'red', showInLegend = FALSE, enableMouseTracking = FALSE, stack = 'diff') %>% 
      hc_add_series(macd$macd, yAxis = y_macd, name = 'MACD', color = 'blue', showInLegend = FALSE) %>% 
      hc_add_series(macd$signal, yAxis = y_macd, name = 'Signal Line', color = 'orange', showInLegend = FALSE)
  }
  
  if(show_rsi){
    hcChart <- hcChart %>%
      ## RSI
      hc_add_series(RSI(df[, 4]), yAxis = y_rsi, name = "Relative Stregth Index", color = hex_to_rgba("green", 0.7), showInLegend = FALSE) %>%
      hc_add_series(xts(rep(70, NROW(df)), index(df)), color = hex_to_rgba("red", 0.7), yAxis = y_rsi, name = "Sell level", enableMouseTracking = FALSE, dashStyle = 'LongDash') %>%
      hc_add_series(xts(rep(30, NROW(df)), index(df)), color = hex_to_rgba("blue", 0.7), yAxis = y_rsi, name = "Buy level", enableMouseTracking = FALSE, dashStyle = 'LongDash') %>% 
      # decimals setting
      hc_tooltip(valueDecimals = 2)
  }  
  
  
  if(show_ma){
    hcChart <- hcChart %>%
      ## Moving Averages
      hc_add_series(short_ma, yAxis = 0, name = 'Short Moving Average', color = 'seagreen', enableMouseTracking = FALSE) %>%
      hc_add_series(long_ma, yAxis = 0, name = 'Long Moving Average', color = 'skyblue', enableMouseTracking = FALSE)
  }
  
  
  if(show_bbands){
    # calculate Bollinger bands position
    bbands <- BBands(df[,2:4])
    hcChart <- hcChart %>%
      ## Add Bollinger Bands
      hc_add_series(bbands[, 'up'], yAxis = 0, name = 'Bollinger Bands', color = '#ccc', enableMouseTracking = FALSE, showInLegend = FALSE) %>%
      hc_add_series(bbands[, 'dn'], yAxis = 0, name = 'Bollinger Bands', color = '#ccc', enableMouseTracking = FALSE) %>% 
      hc_add_series(bbands[, 'mavg'], yAxis = 0, name = 'Moving Average (20)', color = '#E377C2', enableMouseTracking = FALSE)
  }
  
  
  hcChart %>%
    # add title
    hc_title(text = paste(ticker, ticker_name, sep = ' - '), align = 'left', x = 30) %>% 
    # add series
    ## candlechart
    hc_add_series(df, yAxis = 0, name = ticker, showInLegend = FALSE) %>%
    # add legend
    hc_legend(enabled = TRUE, align = 'center') %>% 
    # set theme
    hc_add_theme(hc_theme_db())
}


hcPlotStock(df, name, ticker)
hcPlotStock(df, name, ticker, FALSE, TRUE, TRUE, TRUE, TRUE)
hcPlotStock(df, name, ticker, TRUE, FALSE, FALSE, TRUE, FALSE)
hcPlotStock(df, name, ticker, FALSE, FALSE, FALSE, TRUE, TRUE)